package service.impl;

import model.KeyValue;
import model.Collection;
import service.DatabaseService;
import utils.FileUtils;
import utils.JsonUtils;

import lombok.extern.slf4j.Slf4j;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.stream.Collectors;

/**
 * 数据库服务实现类
 * 使用单例模式和读写锁保证线程安全
 */
@Slf4j
public class DatabaseServiceImpl implements DatabaseService {
    
    // 单例实例
    private static volatile DatabaseServiceImpl instance;
    
    // 主数据存储（使用ConcurrentHashMap保证线程安全）
    private final Map<String, Object> dataStore;
    
    // 集合管理（使用ConcurrentHashMap保证线程安全）
    private final Map<String, Collection> collections;
    
    // 读写锁（用于复杂操作的同步）
    private final ReadWriteLock lock;
    
    // 数据文件路径
    private static final String DATA_FILE = "data/database.json";
    private static final String COLLECTIONS_FILE = "data/collections.json";
    
    // 新增：主从同步服务
    private service.ReplicationService replicationService;
    private boolean isMaster = true; // 这里假设主节点，实际可根据配置判断
    
    private DatabaseServiceImpl() {
        this.dataStore = new ConcurrentHashMap<>();
        this.collections = new ConcurrentHashMap<>();
        this.lock = new ReentrantReadWriteLock();
        loadDataFromFile();
    }
    
    /**
     * 获取单例实例（双重检查锁定）
     */
    public static DatabaseServiceImpl getInstance() {
        if (instance == null) {
            synchronized (DatabaseServiceImpl.class) {
                if (instance == null) {
                    instance = new DatabaseServiceImpl();
                }
            }
        }
        return instance;
    }
    
    public void setReplicationService(service.ReplicationService replicationService) {
        this.replicationService = replicationService;
    }
    public void setIsMaster(boolean isMaster) {
        this.isMaster = isMaster;
    }
    
    // 新增重载：允许外部控制写权限（非接口方法）
    public <T> boolean put(String key, T value, boolean allowWrite) {
        if (!isMaster && allowWrite) {
            log.error("[安全警告] 副节点被错误允许写入: key={}, value={}", key, value);
            throw new IllegalStateException("副节点禁止写入操作！");
        }
        if (!allowWrite) {
            log.warn("从节点拒绝写入: key={}", key);
            return false;
        }
        return putInternal(key, value);
    }
    private <T> boolean putInternal(String key, T value) {
        try {
            if (dataStore.containsKey(key)) {
                Object obj = dataStore.get(key);
                if (obj instanceof KeyValue) {
                    KeyValue<T> keyValue = (KeyValue<T>) obj;
                    if (!keyValue.getDeleted()) {
                        log.warn("键已存在: key={}", key);
                        return false;
                    }
                } else {
                    log.warn("键已存在: key={}", key);
                    return false;
                }
            }
            KeyValue<T> keyValue = new KeyValue<>(key, value);
            dataStore.put(key, keyValue);
            saveDataToFile();
            log.info("成功存储键值对: key={}, value={}", key, value);
            // 主从同步
            if (isMaster && replicationService != null) {
                dto.Request req = new dto.Request(dto.Request.RequestType.PUT);
                req.setKey(key);
                req.setValue(value);
                req.setValueType(value.getClass().getName());
                replicationService.replicateAsync(req);
            }
            return true;
        } catch (Exception e) {
            log.error("存储键值对失败: key={}, error={}", key, e.getMessage());
            return false;
        }
    }
    @Override
    public <T> boolean put(String key, T value) {
        return put(key, value, isMaster);
    }
    
    @Override
    @SuppressWarnings("unchecked")
    public <T> T get(String key, Class<T> clazz) {
        try {
            Object obj = dataStore.get(key);
            if (obj instanceof KeyValue) {
                KeyValue<?> keyValue = (KeyValue<?>) obj;
                if (!keyValue.getDeleted()) {
                    Object value = keyValue.getValue();
                    if (clazz.isInstance(value)) {
                        return clazz.cast(value);
                    }
                }
            }
            return null;
        } catch (Exception e) {
            log.error("获取值失败: key={}, error={}", key, e.getMessage());
            return null;
        }
    }
    
    public boolean update(String key, Object value, boolean allowWrite) {
        if (!isMaster && allowWrite) {
            log.error("[安全警告] 副节点被错误允许更新: key={}, value={}", key, value);
            throw new IllegalStateException("副节点禁止更新操作！");
        }
        if (!allowWrite) {
            log.warn("从节点拒绝更新: key={}", key);
            return false;
        }
        return updateInternal(key, value);
    }
    private boolean updateInternal(String key, Object value) {
        try {
            lock.writeLock().lock();
            Object obj = dataStore.get(key);
            if (obj instanceof KeyValue) {
                KeyValue<Object> keyValue = (KeyValue<Object>) obj;
                keyValue.updateValue(value);
                saveDataToFile();
                log.info("成功更新键值对: key={}, value={}", key, value);
                // 主从同步
                if (isMaster && replicationService != null) {
                    dto.Request req = new dto.Request(dto.Request.RequestType.UPDATE);
                    req.setKey(key);
                    req.setValue(value);
                    req.setValueType(value.getClass().getName());
                    replicationService.replicateAsync(req);
                }
                return true;
            }
            return false;
        } catch (Exception e) {
            log.error("更新键值对失败: key={}, error={}", key, e.getMessage());
            return false;
        } finally {
            lock.writeLock().unlock();
        }
    }
    @Override
    public boolean update(String key, Object value) {
        return update(key, value, isMaster);
    }
    
    public boolean delete(String key, boolean allowWrite) {
        if (!isMaster && allowWrite) {
            log.error("[安全警告] 副节点被错误允许删除: key={}", key);
            throw new IllegalStateException("副节点禁止删除操作！");
        }
        if (!allowWrite) {
            log.warn("从节点拒绝删除: key={}", key);
            return false;
        }
        return deleteInternal(key);
    }
    private boolean deleteInternal(String key) {
        try {
            lock.writeLock().lock();
            Object obj = dataStore.get(key);
            if (obj instanceof KeyValue) {
                @SuppressWarnings("unchecked")
                KeyValue<?> keyValue = (KeyValue<?>) obj;
                keyValue.markAsDeleted();
                saveDataToFile();
                log.info("成功删除键值对: key={}", key);
                // 主从同步
                if (isMaster && replicationService != null) {
                    dto.Request req = new dto.Request(dto.Request.RequestType.DELETE);
                    req.setKey(key);
                    replicationService.replicateAsync(req);
                }
                return true;
            }
            return false;
        } catch (Exception e) {
            log.error("删除键值对失败: key={}, error={}", key, e.getMessage());
            return false;
        } finally {
            lock.writeLock().unlock();
        }
    }
    @Override
    public boolean delete(String key) {
        return delete(key, isMaster);
    }
    
    @Override
    public boolean containsKey(String key) {
        try {
            lock.readLock().lock();
            Object obj = dataStore.get(key);
            if (obj instanceof KeyValue) {
                return !((KeyValue<?>) obj).getDeleted();
            }
            return false;
        } finally {
            lock.readLock().unlock();
        }
    }
    
    @Override
    public List<String> getAllKeys() {
        try {
            lock.readLock().lock();
            return dataStore.entrySet().stream()
                    .filter(entry -> entry.getValue() instanceof KeyValue)
                    .filter(entry -> !((KeyValue<?>) entry.getValue()).getDeleted())
                    .map(Map.Entry::getKey)
                    .collect(Collectors.toList());
        } finally {
            lock.readLock().unlock();
        }
    }
    
    @Override
    @SuppressWarnings("unchecked")
    public <T> List<KeyValue<T>> getAllKeyValues(Class<T> clazz) {
        try {
            lock.readLock().lock();
            return dataStore.values().stream()
                    .filter(obj -> obj instanceof KeyValue)
                    .map(obj -> (KeyValue<T>) obj)
                    .filter(keyValue -> !keyValue.getDeleted())
                    .collect(Collectors.toList());
        } finally {
            lock.readLock().unlock();
        }
    }
    
    @Override
    public <T> boolean batchPut(Map<String, T> keyValueMap) {
        try {
            lock.writeLock().lock();
            for (Map.Entry<String, T> entry : keyValueMap.entrySet()) {
                KeyValue<T> keyValue = new KeyValue<>(entry.getKey(), entry.getValue());
                dataStore.put(entry.getKey(), keyValue);
            }
            saveDataToFile();
            log.info("批量插入成功，共插入{}条数据", keyValueMap.size());
            return true;
        } catch (Exception e) {
            log.error("批量插入失败: error={}", e.getMessage());
            return false;
        } finally {
            lock.writeLock().unlock();
        }
    }
    
    @Override
    public <T> boolean batchUpdate(Map<String, T> keyValueMap) {
        try {
            lock.writeLock().lock();
            int successCount = 0;
            for (Map.Entry<String, T> entry : keyValueMap.entrySet()) {
                if (update(entry.getKey(), entry.getValue())) {
                    successCount++;
                }
            }
            log.info("批量更新完成，成功更新{}条数据", successCount);
            return successCount > 0;
        } finally {
            lock.writeLock().unlock();
        }
    }
    
    @Override
    public boolean batchDelete(List<String> keys) {
        try {
            lock.writeLock().lock();
            int successCount = 0;
            for (String key : keys) {
                if (delete(key)) {
                    successCount++;
                }
            }
            log.info("批量删除完成，成功删除{}条数据", successCount);
            return successCount > 0;
        } finally {
            lock.writeLock().unlock();
        }
    }
    
    @Override
    public boolean createCollection(String name, String description) {
        try {
            if (collections.containsKey(name)) {
                log.warn("集合已存在: name={}", name);
                return false;
            }
            Collection collection = new Collection(name, description);
            collections.put(name, collection);
            saveCollectionsToFile();
            log.info("成功创建集合: name={}, description={}", name, description);
            return true;
        } catch (Exception e) {
            log.error("创建集合失败: name={}, error={}", name, e.getMessage());
            return false;
        }
    }
    
    @Override
    public boolean deleteCollection(String name) {
        try {
            Collection removed = collections.remove(name);
            if (removed != null) {
                saveCollectionsToFile();
                log.info("成功删除集合: name={}", name);
                return true;
            }
            return false;
        } catch (Exception e) {
            log.error("删除集合失败: name={}, error={}", name, e.getMessage());
            return false;
        }
    }
    
    @Override
    public Collection getCollection(String name) {
        return collections.get(name);
    }
    
    @Override
    public List<Collection> getAllCollections() {
        return new ArrayList<>(collections.values());
    }
    
    @Override
    public <T> boolean putInCollection(String collectionName, String key, T value) {
        try {
            Collection collection = collections.get(collectionName);
            if (collection == null) {
                log.warn("集合不存在: name={}", collectionName);
                return false;
            }
            collection.put(key, value);
            saveCollectionsToFile();
            log.info("在集合{}中成功存储数据: key={}", collectionName, key);
            return true;
        } catch (Exception e) {
            log.error("在集合中存储数据失败: collection={}, key={}, error={}", 
                     collectionName, key, e.getMessage());
            return false;
        }
    }
    
    @Override
    @SuppressWarnings("unchecked")
    public <T> T getFromCollection(String collectionName, String key, Class<T> clazz) {
        try {
            Collection collection = collections.get(collectionName);
            if (collection == null) {
                return null;
            }
            Object value = collection.get(key);
            if (value != null && clazz.isInstance(value)) {
                return (T) value;
            }
            return null;
        } catch (Exception e) {
            log.error("从集合获取数据失败: collection={}, key={}, error={}", 
                     collectionName, key, e.getMessage());
            return null;
        }
    }
    
    @Override
    public boolean deleteFromCollection(String collectionName, String key) {
        try {
            Collection collection = collections.get(collectionName);
            if (collection == null) {
                return false;
            }
            Object removed = collection.remove(key);
            if (removed != null) {
                saveCollectionsToFile();
                log.info("从集合{}中成功删除数据: key={}", collectionName, key);
                return true;
            }
            return false;
        } catch (Exception e) {
            log.error("从集合删除数据失败: collection={}, key={}, error={}", 
                     collectionName, key, e.getMessage());
            return false;
        }
    }
    
    @Override
    @SuppressWarnings("unchecked")
    public <T> List<KeyValue<T>> getAllFromCollection(String collectionName, Class<T> clazz) {
        try {
            Collection collection = collections.get(collectionName);
            if (collection == null) {
                return new ArrayList<>();
            }
            
            List<KeyValue<T>> result = new ArrayList<>();
            for (Map.Entry<String, Object> entry : collection.getData().entrySet()) {
                if (clazz.isInstance(entry.getValue())) {
                    KeyValue<T> keyValue = new KeyValue<>(entry.getKey(), (T) entry.getValue());
                    result.add(keyValue);
                }
            }
            return result;
        } catch (Exception e) {
            log.error("获取集合所有数据失败: collection={}, error={}", collectionName, e.getMessage());
            return new ArrayList<>();
        }
    }
    
    @Override
    public void clear() {
        try {
            lock.writeLock().lock();
            dataStore.clear();
            collections.clear();
            saveDataToFile();
            saveCollectionsToFile();
            log.info("数据库已清空");
        } finally {
            lock.writeLock().unlock();
        }
    }
    
    @Override
    public Map<String, Object> getStatistics() {
        try {
            lock.readLock().lock();
            Map<String, Object> stats = new HashMap<>();
            stats.put("totalKeys", dataStore.size());
            stats.put("activeKeys", getAllKeys().size());
            stats.put("collections", collections.size());
            stats.put("collectionNames", new ArrayList<>(collections.keySet()));
            return stats;
        } finally {
            lock.readLock().unlock();
        }
    }
    
    @Override
    public KeyValue<?> getWithType(String key) {
        Object obj = dataStore.get(key);
        if (obj instanceof KeyValue) {
            return (KeyValue<?>) obj;
        }
        return null;
    }
    
    /**
     * 从文件加载数据
     */
    private void loadDataFromFile() {
        try {
            String dataJson = FileUtils.readFile(DATA_FILE);
            if (dataJson != null && !dataJson.trim().isEmpty()) {
                Map<String, model.KeyValue> loadedData = utils.JsonUtils.parseKeyValueMap(dataJson);
                dataStore.putAll(loadedData);
                log.info("从文件加载数据成功，共加载{}条记录", loadedData.size());
            }
            
            String collectionsJson = FileUtils.readFile(COLLECTIONS_FILE);
            if (collectionsJson != null && !collectionsJson.trim().isEmpty()) {
                Map<String, Collection> loadedCollections = JsonUtils.parseCollections(collectionsJson);
                collections.putAll(loadedCollections);
                log.info("从文件加载集合成功，共加载{}个集合", loadedCollections.size());
            }
        } catch (Exception e) {
            log.error("从文件加载数据失败: error={}", e.getMessage());
        }
    }
    
    /**
     * 保存数据到文件
     */
    public void saveDataToFile() {
        try {
            String json = JsonUtils.toJson(dataStore);
            FileUtils.writeFile(DATA_FILE, json);
        } catch (Exception e) {
            log.error("保存数据到文件失败: error={}", e.getMessage());
        }
    }
    
    /**
     * 保存集合到文件
     */
    public void saveCollectionsToFile() {
        try {
            String json = JsonUtils.toJson(collections);
            FileUtils.writeFile(COLLECTIONS_FILE, json);
        } catch (Exception e) {
            log.error("保存集合到文件失败: error={}", e.getMessage());
        }
    }
} 